home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / edit / jwpsrc.zip / HOTKEYS.C < prev    next >
C/C++ Source or Header  |  1993-03-31  |  67KB  |  1,833 lines

  1. /* Copyright (C) Stephen Chung, 1991-1993.  All rights reserved. */
  2.  
  3. #include "jwp.h"
  4.  
  5. #include "idm.h"
  6.  
  7. #include <math.h>
  8.  
  9.  
  10. #define CTRLCHAR    '^'
  11. #define SHIFTCHAR   '+'
  12.  
  13. #define TTYPE_FONTTYPE      0x04
  14. #define PSBLOCKSIZE         20
  15.  
  16. #define MAXUNDOLEVELS       32000
  17. #define DEFUNDOLEVELS       50
  18.  
  19.  
  20. typedef struct {
  21.     BOOL ctrl;
  22.     BOOL shift;
  23.     char alpha;
  24.     WORD scancode;
  25. } HOTKEY;
  26.  
  27.  
  28. typedef struct {
  29.     char *desc;
  30.     int menuid;
  31.     HOTKEY hotkey;
  32. } JWPFUNC;
  33.  
  34.  
  35. #define ALPHASTART      4221
  36. #define FUNCSTART       4251
  37.  
  38. static FARPROC OldStaticProc;
  39. static int Selected;
  40. static int CurrentFunction = 1;
  41.  
  42. static HOTKEY OldKey, CurrentKey;
  43.  
  44. static JWPFUNC jwpfunc[] = {
  45.     { "Create New File",        IDM_FILENEW,            { 1, 0, 'N', 0 } },
  46.     { "Open File",              IDM_FILEOPEN,           { 1, 0, 'O', 0 } },
  47.     { "Close File",             IDM_FILECLOSE,          { 1, 0, 'X', 0 } },
  48.     { "Save File",              IDM_FILESAVE,           { 0, 0, 0, VK_F11 } },
  49.     { "Save as Something Else", IDM_FILESAVEAS,         { 0, 0, 0, VK_F12 } },
  50.     { "Find File",              IDM_FILEFIND,           { 0, 0, 0, 0 } },
  51.     { "Print File",             IDM_FILEPRINT,          { 1, 0, 'P', 0 } },
  52. //  { "Print Preview",          IDM_FILEPREVIEW,        { 1, 0, 'V', 0 } },
  53.     { "Printer Setup",          IDM_FILEPRINTER,        { 0, 0, 0, 0 } },
  54.     { "Edit File Summary",      IDM_FILESUMMARY,        { 0, 0, 0, 0 } },
  55.     { "Edit Header/Footer",     IDM_FILEHEADERS,        { 0, 0, 0, 0 } },
  56.     { "Toggle Kana/Text mode",  IDM_TOGGLEMODE,         { 0, 0, 0, VK_F4 } },
  57.     { "Toggle Glossary List",   IDM_VIEWGLOSSARY,       { 1, 0, 'G', 0 } },
  58.     { "Toggle Draft View",      IDM_VIEWDRAFT,          { 1, 0, 0, VK_F2 } },
  59.     { "Toggle Iconbar",         IDM_VIEWRIBBON,         { 0, 0, 0, 0 } },
  60.     { "Toggle Status Bar",      IDM_VIEWSPECIAL,        { 0, 0, 0, 0 } },
  61.     { "Toggle File Ruler",      IDM_VIEWSPECIAL,        { 0, 0, 0, 0 } },
  62.     { "Toggle Special Symbols", IDM_VIEWSPECIAL,        { 0, 0, 0, 0 } },
  63.     { "Toggle Dynamic Glossary",IDM_TOGGLEGLOSSARY,     { 0, 0, 0, 0 } },
  64.     { "Search for Text",        IDM_EDITSEARCH,         { 1, 0, 'S', 0 } },
  65.     { "Continue Search/Replace",IDM_CONTINUESEARCH,     { 0, 0, 0, 0 } },
  66.     { "Replace Text",           IDM_EDITREPLACE,        { 1, 0, 'R', 0 } },
  67.     { "Convert Kana to Kanji (L->R)", IDM_KANJICONVERT, { 0, 0, 0, VK_F2 } },
  68.     { "Convert Kana to Kanji (R->L)", IDM_KANJILCONVERT,{ 0, 1, 0, VK_F2 } },
  69. //  { "Revert Kanji to Kana",   IDM_KANJIREVERSE,       { 0, 0, 0, 0 } },
  70.     { "Kanji Lookup",           IDM_KANJILOOKUP,        { 1, 0, 'L', 0 } },
  71.     { "Kanji Info",             IDM_KANJIINFO,          { 1, 0, 'K', 0 } },
  72.     { "JIS Input",              IDM_KANJIINPUT,         { 1, 0, 'J', 0 } },
  73.     { "JIS Table",              IDM_KANJITABLE,         { 1, 0, 'T', 0 } },
  74.     { "Format Paragraph",       IDM_FORMATPARAGRAPH,    { 0, 0, 0, 0 } },
  75.     { "Page Setup",             IDM_FORMATPAGE,         { 0, 0, 0, 0 } },
  76.     { "Set Options",            IDM_UTILITIESOPTIONS,   { 0, 0, 0, 0 } },
  77.     { "Change Hot Keys",        IDM_UTILITIESHOTKEYS,   { 0, 0, 0, 0 } },
  78.     { "Maintain Kanji Fonts",   IDM_UTILITIESFONTS,     { 0, 0, 0, 0 } },
  79.     { "Show Statistics",        IDM_UTILITIESSTAT,      { 0, 0, 0, 0 } },
  80.     { "Dictionary",             IDM_UTILITIESDICT,      { 0, 0, 0, VK_F6 } },
  81.     { "Edit Glossary",          IDM_UTILITIESGLOSSARY,  { 0, 0, 0, 0 } },
  82.     { "Edit User Conversions",  IDM_UTILITIESCONVERT,   { 0, 0, 0, 0 } },
  83.     { "Cascade File Windows",   IDM_WINDOWCASCADE,      { 0, 1, 0, VK_F4 } },
  84.     { "Tile File Windows",      IDM_WINDOWTILE,         { 0, 1, 0, VK_F5 } },
  85.     { "Close all File Windows", IDM_WINDOWCLOSE,        { 0, 0, 0, 0 } },
  86.     { "Help",                   IDM_HELPINDEX,          { 0, 0, 0, VK_F1 } }
  87. };
  88.  
  89. #define NRJWPFUNC   (sizeof(jwpfunc) / sizeof(JWPFUNC))
  90.  
  91. static HOTKEY HotKeysBackup[NRJWPFUNC];
  92. BOOL OptionsChanged = FALSE;
  93.  
  94. static double far *PointSizes = NULL;
  95.  
  96. /* Option backup's */
  97.  
  98. static RECT glistsize, convbar;
  99. static FILEFORMAT clipboard;
  100. static BOOL DraftView, ShowSpecial, ShowRuler, NNConvert;
  101. static BOOL ProgramMaximized;
  102. static RECT ProgramPosition;
  103. static int SysFontNum, BaseFontNum, PrintFontNum;
  104. static char *AsciiFontName = NULL;
  105. static double AsciiFontSize;
  106. static MEASUREMENT Measure;
  107. static PAGESETUP PageSetup;
  108. static JUSTIFICATION LongJust, ShortJust;
  109. static int UndoLevels, SaveUndoLevels;
  110.  
  111.  
  112.  
  113. WORD DecodeKeyStroke (WORD message, WORD wParam, BOOL shift, BOOL ctrl)
  114. {
  115.     int i;
  116.  
  117.     if (message == WM_KEYDOWN) {
  118.         for (i = 0; i < NRJWPFUNC; i++) {
  119.             if (jwpfunc[i].hotkey.alpha == 0 &&
  120.                 jwpfunc[i].hotkey.scancode == wParam &&
  121.                 jwpfunc[i].hotkey.shift == shift &&
  122.                 jwpfunc[i].hotkey.ctrl == ctrl)
  123.                     return (jwpfunc[i].menuid);
  124.         }
  125.     } else if (message == WM_CHAR) {
  126.         for (i = 0; i < NRJWPFUNC; i++) {
  127.             if (jwpfunc[i].hotkey.alpha == wParam) return (jwpfunc[i].menuid);
  128.         }
  129.     }
  130.  
  131.     return (0);
  132. }
  133.  
  134.  
  135.  
  136. static int ConvertKeyCode (HOTKEY key, char *buffer)
  137. {
  138.     buffer[0] = '\0';
  139.  
  140.     if (key.alpha == 0) {
  141.         if (key.shift) strcat(buffer, "Shift+");
  142.         if (key.ctrl) strcat(buffer, "Ctrl+");
  143.  
  144.         switch (key.scancode) {
  145.             case VK_F1:  strcat(buffer, "F1"); return (FUNCSTART + 0);
  146.             case VK_F2:  strcat(buffer, "F2"); return (FUNCSTART + 1);
  147.             case VK_F3:  strcat(buffer, "F3"); return (FUNCSTART + 2);
  148.             case VK_F4:  strcat(buffer, "F4"); return (FUNCSTART + 3);
  149.             case VK_F5:  strcat(buffer, "F5"); return (FUNCSTART + 4);
  150.             case VK_F6:  strcat(buffer, "F6"); return (FUNCSTART + 5);
  151.             case VK_F7:  strcat(buffer, "F7"); return (FUNCSTART + 6);
  152.             case VK_F8:  strcat(buffer, "F8"); return (FUNCSTART + 7);
  153.             case VK_F9:  strcat(buffer, "F9"); return (FUNCSTART + 8);
  154.             case VK_F10: strcat(buffer, "F10"); return (FUNCSTART + 9);
  155.             case VK_F11: strcat(buffer, "F11"); return (FUNCSTART + 10);
  156.             case VK_F12: strcat(buffer, "F12"); return (FUNCSTART + 11);
  157.         }
  158.  
  159.         return (-1);
  160.     }
  161.  
  162.  
  163.     if (key.alpha < 'A' || key.alpha > 'Z') return (-1);
  164.  
  165.     sprintf(buffer, "Ctrl+%c", key.alpha);
  166.  
  167.     return (ALPHASTART + (key.alpha - 'A'));
  168. }
  169.  
  170.  
  171.  
  172. static void IDToKeyCode (int id, HOTKEY *key)
  173. {
  174.     if (id >= FUNCSTART) {
  175.         key->alpha = 0;
  176.         switch (id - FUNCSTART) {
  177.             case 0:  key->scancode = VK_F1; break;
  178.             case 1:  key->scancode = VK_F2; break;
  179.             case 2:  key->scancode = VK_F3; break;
  180.             case 3:  key->scancode = VK_F4; break;
  181.             case 4:  key->scancode = VK_F5; break;
  182.             case 5:  key->scancode = VK_F6; break;
  183.             case 6:  key->scancode = VK_F7; break;
  184.             case 7:  key->scancode = VK_F8; break;
  185.             case 8:  key->scancode = VK_F9; break;
  186.             case 9:  key->scancode = VK_F10; break;
  187.             case 10: key->scancode = VK_F11; break;
  188.             case 11: key->scancode = VK_F12; break;
  189.             default: key->scancode = VK_F1; break;
  190.         }
  191.     } else {
  192.         key->alpha = 'A' + (id - ALPHASTART);
  193.         key->scancode = 0;
  194.     }
  195. }
  196.  
  197.  
  198. static BOOL HotKeyEqual (HOTKEY k1, HOTKEY k2)
  199. {
  200.     if (k1.alpha == 0) {
  201.         return (k1.shift == k2.shift &&
  202.                 k1.ctrl == k2.ctrl &&
  203.                 k1.scancode == k2.scancode);
  204.     } else {
  205.         return (k1.alpha == k2.alpha);
  206.     }
  207. }
  208.  
  209.  
  210.  
  211. void ProcessMenuTexts (void)
  212. {
  213.     int i, j;
  214.     WORD menuid;
  215.     char buffer[MAXLINELEN], keytext[50];
  216.  
  217.     for (i = 0; i < NRJWPFUNC; i++) {
  218.         menuid = jwpfunc[i].menuid;
  219.         GetMenuString(hmenu, menuid, buffer, MAXLINELEN, MF_BYCOMMAND);
  220.  
  221.         for (j = 0; buffer[j] && buffer[j] != '\t'; j++);
  222.         buffer[j] = '\0';
  223.  
  224.         if (ConvertKeyCode(jwpfunc[i].hotkey, keytext) >= 0) {
  225.             strcat(buffer, "\t");
  226.             strcat(buffer, keytext);
  227.         }
  228.  
  229.         j = GetMenuState(hmenu, menuid, MF_BYCOMMAND);
  230.         j |= (MF_BYCOMMAND | MF_STRING);
  231.  
  232.         ModifyMenu(hmenu, menuid, j, menuid, buffer);
  233.     }
  234.  
  235.     /* Now check the menu items */
  236.  
  237.     if (global.draftview)
  238.         CheckMenuItem(hmenu, IDM_VIEWDRAFT, MF_CHECKED | MF_BYCOMMAND);
  239.     if (global.showruler)
  240.         CheckMenuItem(hmenu, IDM_VIEWRULER, MF_CHECKED | MF_BYCOMMAND);
  241.     if (global.tbhwnd != NULL)
  242.         CheckMenuItem(hmenu, IDM_VIEWRIBBON, MF_CHECKED | MF_BYCOMMAND);
  243.     if (global.statushwnd != NULL)
  244.         CheckMenuItem(hmenu, IDM_VIEWSTATUS, MF_CHECKED | MF_BYCOMMAND);
  245.     if (global.glisthwnd != NULL)
  246.         CheckMenuItem(hmenu, IDM_VIEWGLOSSARY, MF_CHECKED | MF_BYCOMMAND);
  247.     if (global.showspecial)
  248.         CheckMenuItem(hmenu, IDM_VIEWSPECIAL, MF_CHECKED | MF_BYCOMMAND);
  249. }
  250.  
  251.  
  252.  
  253. LONG FAR PASCAL HotKeyChoiceProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  254. {
  255.     switch (message) {
  256.         case WM_LBUTTONDOWN: {
  257.             int i;
  258.             HWND OldSelected;
  259.  
  260.             i = GetDlgCtrlID(hwnd);
  261.             if (i == Selected) return (0);
  262.  
  263.             OldSelected = GetDlgItem(GetParent(hwnd), Selected);
  264.             SendMessage(hwnd, WM_USER, 0, 0L);
  265.             SendMessage(OldSelected, WM_USER, 0, 0L);
  266.  
  267.             Selected = i;
  268.             IDToKeyCode(i, &CurrentKey);
  269.             EnableWindow(GetDlgItem(GetParent(hwnd), 4211), (CurrentKey.alpha == 0));
  270.             EnableWindow(GetDlgItem(GetParent(hwnd), 4212), (CurrentKey.alpha == 0));
  271.  
  272.             SendMessage(GetParent(hwnd), WM_USER, 0, 0L);
  273.             return (0);
  274.         }
  275.  
  276.         case WM_USER: {
  277.             RECT rect;
  278.             HDC hdc;
  279.  
  280.             GetClientRect(hwnd, &rect);
  281.             hdc = GetDC(hwnd);
  282.             PatBlt(hdc, 1, 1, rect.right - 2, rect.bottom - 2, DSTINVERT);
  283.             ReleaseDC(hwnd, hdc);
  284.             return (TRUE);
  285.         }
  286.  
  287.         case WM_PAINT: {
  288.             int i, width, height;
  289.             DWORD dimensions;
  290.             HDC hdc;
  291.             PAINTSTRUCT ps;
  292.             RECT rect;
  293.             char buf[5];
  294.  
  295.             GetClientRect(hwnd, &rect);
  296.  
  297.             hdc = BeginPaint(hwnd, &ps);
  298.             Create3DEffect (hdc, &rect, 1, 0);
  299.             SetBkMode(hdc, TRANSPARENT);
  300.  
  301.             i = GetDlgCtrlID(hwnd);
  302.  
  303.             if (i >= FUNCSTART) {
  304.                 sprintf(buf, "F%d", i - FUNCSTART + 1);
  305.  
  306.                 dimensions = GetTextExtent(hdc, buf, strlen(buf));
  307.             } else {
  308.                 sprintf(buf, "%c", 'A' + (i - ALPHASTART));
  309.  
  310.                 dimensions = GetTextExtent(hdc, buf, 1);
  311.             }
  312.  
  313.             width = LOWORD(dimensions);
  314.             height = HIWORD(dimensions);
  315.  
  316.             TextOut(hdc, (rect.right - width) / 2, (rect.bottom - height) / 2,
  317.                     buf, strlen(buf));
  318.  
  319.             if (i == Selected)
  320.                 PatBlt(hdc, 1, 1, rect.right - 2, rect.bottom - 2, DSTINVERT);
  321.  
  322.             EndPaint(hwnd, &ps);
  323.             return (0);
  324.         }
  325.  
  326.         default: break;
  327.     }
  328.  
  329.     return (CallWindowProc(OldStaticProc, hwnd, message, wParam, lParam));
  330. }
  331.  
  332.  
  333.  
  334. BOOL FAR PASCAL ChangeHotKeyProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  335. {
  336.     int i;
  337.     POINT point;
  338.     HWND child;
  339.     char buffer[MAXLINELEN], keytext[50];
  340.  
  341.     switch (message) {
  342.         case WM_INITDIALOG:
  343.             OldStaticProc = (FARPROC) GetWindowLong(GetDlgItem(hwnd, ALPHASTART), GWL_WNDPROC);
  344.  
  345.             for (i = 0; i < 26; i++) {
  346.                 if (strchr("HIM", 'A' + i) != NULL) continue;
  347.                 SetWindowLong(GetDlgItem(hwnd, ALPHASTART + i), GWL_WNDPROC, (LONG) HotKeyChoiceProc);
  348.             }
  349.  
  350.             for (i = 0; i < 12; i++)
  351.                 SetWindowLong(GetDlgItem(hwnd, FUNCSTART + i), GWL_WNDPROC, (LONG) HotKeyChoiceProc);
  352.  
  353.             Selected = ConvertKeyCode(OldKey, keytext);
  354.             CurrentKey = OldKey;
  355.  
  356.             sprintf(buffer, "Hot Key for \"%s\"", jwpfunc[CurrentFunction].desc);
  357.             SetDlgItemText(hwnd, 4201, buffer);
  358.  
  359.             if (Selected >= 0) {
  360.                 sprintf(buffer, "Old Hot Key:\t%s", keytext);
  361.                 SetDlgItemText(hwnd, 4202, buffer);
  362.                 sprintf(buffer, "New Hot Key:\t%s", keytext);
  363.                 SetDlgItemText(hwnd, 4203, buffer);
  364.             } else {
  365.                 SetDlgItemText(hwnd, 4202, "Old Hot Key:\tNone");
  366.                 SetDlgItemText(hwnd, 4203, "New Hot Key:\tNone");
  367.             }
  368.  
  369.             CheckDlgButton(hwnd, 4211, OldKey.ctrl);
  370.             CheckDlgButton(hwnd, 4212, OldKey.shift);
  371.  
  372.             EnableWindow(GetDlgItem(hwnd, 4211), (CurrentKey.alpha == 0));
  373.             EnableWindow(GetDlgItem(hwnd, 4212), (CurrentKey.alpha == 0));
  374.  
  375.             CenterDialogBox(hwnd);
  376.  
  377.             return (TRUE);
  378.  
  379.         case WM_LBUTTONDOWN:
  380.  
  381.             point.x = LOWORD(lParam);
  382.             point.y = HIWORD(lParam);
  383.  
  384.             child = ChildWindowFromPoint(hwnd, point);
  385.  
  386.             if (child == hwnd || child == NULL) return (TRUE);
  387.  
  388.             for (i = 0; i < 26; i++) {
  389.                 if (child == GetDlgItem(hwnd, ALPHASTART + i)) {
  390.                     SendDlgItemMessage(hwnd, ALPHASTART + i, WM_LBUTTONDOWN, wParam, lParam);
  391.                     return (TRUE);
  392.                 }
  393.             }
  394.             for (i = 0; i < 12; i++) {
  395.                 if (child == GetDlgItem(hwnd, FUNCSTART + i)) {
  396.                     SendDlgItemMessage(hwnd, FUNCSTART + i, WM_LBUTTONDOWN, wParam, lParam);
  397.                     return (TRUE);
  398.                 }
  399.             }
  400.  
  401.             return (TRUE);
  402.  
  403.         case WM_USER:
  404.             if (ConvertKeyCode(CurrentKey, keytext) >= 0) {
  405.                 sprintf(buffer, "New Hot Key:\t%s", keytext);
  406.                 SetDlgItemText(hwnd, 4203, buffer);
  407.             } else {
  408.                 SetDlgItemText(hwnd, 4203, "New Hot Key:\tNone");
  409.             }
  410.             return (TRUE);
  411.  
  412.         case WM_COMMAND:
  413.             switch (wParam) {
  414.                 case 4211:      /* Check boxes */
  415.                 case 4212:
  416.                     CurrentKey.ctrl = IsDlgButtonChecked(hwnd, 4211);
  417.                     CurrentKey.shift = IsDlgButtonChecked(hwnd, 4212);
  418.  
  419.                     if (ConvertKeyCode(CurrentKey, keytext) >= 0) {
  420.                         sprintf(buffer, "New Hot Key:\t%s", keytext);
  421.                         SetDlgItemText(hwnd, 4203, buffer);
  422.                     }
  423.                     return (TRUE);
  424.  
  425.                 case IDOK:
  426.                     if (CurrentKey.alpha != 0 && strchr("HIM", CurrentKey.alpha) != NULL) {
  427.                         ConvertKeyCode(CurrentKey, keytext);
  428.                         ErrorMessage(hwnd, "You cannot assign %s to anything", keytext);
  429.                         return (TRUE);
  430.                     }
  431.  
  432.                     for (i = 0; i < NRJWPFUNC; i++) {
  433.                         if (i == CurrentFunction) continue;
  434.                         if (HotKeyEqual(CurrentKey, jwpfunc[i].hotkey)) break;
  435.                     }
  436.  
  437.                     if (i < NRJWPFUNC) {
  438.                         if (ConvertKeyCode(CurrentKey, keytext) >= 0) {
  439.                             ErrorMessage(hwnd, "The key %s is already assigned to\n"
  440.                                                   "\"%s\"", keytext, jwpfunc[i].desc);
  441.                             return (TRUE);
  442.                         }
  443.                     }
  444.  
  445.                     if (CurrentKey.alpha != 0) CurrentKey.shift = CurrentKey.ctrl = FALSE;
  446.  
  447.                     jwpfunc[CurrentFunction].hotkey = CurrentKey;
  448.  
  449.                     OptionsChanged = TRUE;
  450.  
  451.                     ProcessMenuTexts();
  452.                     EndDialog(hwnd, FALSE);
  453.                     return (TRUE);
  454.  
  455.                 case IDCANCEL:
  456.                     EndDialog(hwnd, FALSE);
  457.                     return (TRUE);
  458.             }
  459.     }
  460.  
  461.     return (FALSE);
  462. }
  463.  
  464.  
  465.  
  466. BOOL FAR PASCAL HotKeysProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  467. {
  468.     int i;
  469.  
  470.     switch (message) {
  471.         case WM_INITDIALOG: {
  472.             char buffer[MAXLINELEN];
  473.  
  474.             for (i = 0; i < NRJWPFUNC; i++) {
  475.                 SendDlgItemMessage(hwnd, 4201, LB_ADDSTRING, 0, (LONG) jwpfunc[i].desc);
  476.                 HotKeysBackup[i] = jwpfunc[i].hotkey;
  477.             }
  478.  
  479.             SendDlgItemMessage(hwnd, 4201, LB_SETCURSEL, 0, 0L);
  480.  
  481.             if (ConvertKeyCode(jwpfunc[0].hotkey, buffer) >= 0) {
  482.                 SetDlgItemText(hwnd, 4202, buffer);
  483.             } else {
  484.                 SetDlgItemText(hwnd, 4202, "None");
  485.             }
  486.  
  487.             CenterDialogBox(hwnd);
  488.  
  489.             return (TRUE);
  490.         }
  491.  
  492.         case WM_COMMAND:
  493.             switch (wParam) {
  494.                 case 4201:      /* List Box */
  495.                     switch (HIWORD(lParam)) {
  496.                         case LBN_SELCHANGE: {
  497.                             char buffer[MAXLINELEN];
  498.  
  499.                             i = SendDlgItemMessage(hwnd, 4201, LB_GETCURSEL, 0, 0L);
  500.                             if (i == LB_ERR) {
  501.                                 MessageBeep(0);
  502.                                 return (TRUE);
  503.                             }
  504.                             if (ConvertKeyCode(jwpfunc[i].hotkey, buffer) >= 0) {
  505.                                 SetDlgItemText(hwnd, 4202, buffer);
  506.                             } else {
  507.                                 SetDlgItemText(hwnd, 4202, "None");
  508.                             }
  509.                             return (TRUE);
  510.                         }
  511.  
  512.                         case LBN_DBLCLK:
  513.                             i = SendDlgItemMessage(hwnd, 4201, LB_GETCURSEL, 0, 0L);
  514.                             if (i == LB_ERR) {
  515.                                 MessageBeep(0);
  516.                                 return (TRUE);
  517.                             }
  518.                             SendMessage(hwnd, WM_COMMAND, 4211, 0L);
  519.                             return (TRUE);
  520.                     }
  521.                     return (TRUE);
  522.  
  523.                 case 4211: {    /* Change */
  524.                     char buffer[MAXLINELEN];
  525.  
  526.                     i = SendDlgItemMessage(hwnd, 4201, LB_GETCURSEL, 0, 0L);
  527.                     if (i == LB_ERR) {
  528.                         MessageBeep(0);
  529.                         return (TRUE);
  530.                     }
  531.                     CurrentFunction = i;
  532.                     OldKey = CurrentKey = jwpfunc[i].hotkey;
  533.  
  534.                     DialogBox (hInstance, "ChangeHotKey", hwnd, ChangeHotKeyProc);
  535.  
  536.                     if (ConvertKeyCode(jwpfunc[i].hotkey, buffer) >= 0) {
  537.                         SetDlgItemText(hwnd, 4202, buffer);
  538.                     } else {
  539.                         SetDlgItemText(hwnd, 4202, "None");
  540.                     }
  541.  
  542.                     return (TRUE);
  543.                 }
  544.  
  545.                 case 4212:      /* Delete */
  546.                     i = SendDlgItemMessage(hwnd, 4201, LB_GETCURSEL, 0, 0L);
  547.                     if (i == LB_ERR) {
  548.                         MessageBeep(0);
  549.                         return (TRUE);
  550.                     }
  551.                     CurrentKey.shift = CurrentKey.alpha = FALSE;
  552.                     CurrentKey.alpha = CurrentKey.scancode = 0;
  553.                     jwpfunc[i].hotkey = CurrentKey;
  554.                     SetDlgItemText(hwnd, 4202, "None");
  555.                     return (TRUE);
  556.  
  557.                 case IDCANCEL:
  558.                     for (i = 0; i < NRJWPFUNC; i++) jwpfunc[i].hotkey = HotKeysBackup[i];
  559.                     EndDialog(hwnd, FALSE);
  560.                     return (TRUE);
  561.  
  562.                 case IDOK:
  563.                     for (i = 0; i < NRJWPFUNC; i++) {
  564.                         if (HotKeysBackup[i].alpha != jwpfunc[i].hotkey.alpha) {
  565.                             OptionsChanged = TRUE;
  566.                             break;
  567.                         }
  568.                         if (jwpfunc[i].hotkey.alpha == 0) {
  569.                             if (jwpfunc[i].hotkey.shift != HotKeysBackup[i].shift ||
  570.                                 jwpfunc[i].hotkey.ctrl != HotKeysBackup[i].ctrl ||
  571.                                 jwpfunc[i].hotkey.scancode != HotKeysBackup[i].scancode)
  572.                                     OptionsChanged = TRUE;
  573.                                     break;
  574.                         }
  575.                     }
  576.  
  577.                     ProcessMenuTexts();
  578.                     EndDialog(hwnd, FALSE);
  579.                     return (TRUE);
  580.             }
  581.     }
  582.  
  583.     return (FALSE);
  584. }
  585.  
  586.  
  587.  
  588. char *DupString (char *s)
  589. {
  590.     char *cp;
  591.  
  592.     cp = MemAlloc(strlen(s) + 5);
  593.  
  594.     if (cp != NULL) strcpy(cp, s);
  595.  
  596.     return (cp);
  597. }
  598.  
  599.  
  600.  
  601. BOOL ReadProgramSizeOptions (int *x, int *y, int *width, int *length)
  602. {
  603.     OFSTRUCT of;
  604.     char buffer[MAXLINELEN];
  605.     char OptionsFileName[MAXFILENAMELEN];
  606.  
  607.     if (OpenFile(PROGNAME ".INI", &of, OF_READ | OF_EXIST) == -1) {
  608.         strcpy(OptionsFileName, PROGNAME ".INI");
  609.     } else {
  610.         strcpy(OptionsFileName, of.szPathName);
  611.     }
  612.  
  613.     GetPrivateProfileString("Others", "Program Size", "500 400", buffer, MAXLINELEN, OptionsFileName);
  614.     sscanf(buffer, "%d %d", width, length);
  615.  
  616.     ProgramPosition.right = *width;
  617.     ProgramPosition.bottom = *length;
  618.  
  619.     GetPrivateProfileString("Others", "Program Position", "Maximized", buffer, MAXLINELEN, OptionsFileName);
  620.  
  621.     if (!stricmp(buffer, "Maximized")) {
  622.         ProgramMaximized = TRUE;
  623.         *x = *y = 0;
  624.         return (TRUE);
  625.     } else {
  626.         ProgramMaximized = TRUE;
  627.         sscanf(buffer, "%d %d", x, y);
  628.         ProgramPosition.left = *x;
  629.         ProgramPosition.top = *y;
  630.         return (FALSE);
  631.     }
  632. }
  633.  
  634.  
  635.  
  636. BOOL Read3DDialogOption (void)
  637. {
  638.     OFSTRUCT of;
  639.     char buffer[MAXLINELEN];
  640.     char OptionsFileName[MAXFILENAMELEN];
  641.  
  642.     if (OpenFile(PROGNAME ".INI", &of, OF_READ | OF_EXIST) == -1) {
  643.         strcpy(OptionsFileName, PROGNAME ".INI");
  644.     } else {
  645.         strcpy(OptionsFileName, of.szPathName);
  646.     }
  647.  
  648.     GetPrivateProfileString("Others", "3D Dialog Boxes", "Yes", buffer, MAXLINELEN, OptionsFileName);
  649.     return (buffer[0] == 'Y' || buffer[0] == 'y');
  650. }
  651.  
  652.  
  653.  
  654. void ReadOptionsFile (void)
  655. {
  656.     int i, j;
  657.     int fd;
  658.     char ch;
  659.     OFSTRUCT of;
  660.     HOTKEY hotkey;
  661.     char buffer[MAXLINELEN];
  662.     char keyname[50];
  663.     char OptionsFileName[MAXFILENAMELEN];
  664.     char SectionName[50];
  665.  
  666.  
  667.     GetWindowsDirectory(buffer, MAXLINELEN);
  668.     i = strlen(buffer);
  669.     if (i > 0 && buffer[i-1] != '\\') {
  670.         buffer[i] = '\\';
  671.         buffer[i+1] = '\0';
  672.     }
  673.     strcat(buffer, PROGNAME ".INI");
  674.  
  675.     if (OpenFile(buffer, &of, OF_READ | OF_EXIST) == -1) {
  676.         ErrorMessage(global.hwnd, "Cannot read initialization file %s!", buffer);
  677.         return;
  678.     } else {
  679.         strcpy(OptionsFileName, of.szPathName);
  680.     }
  681.  
  682.  
  683.     /* Path names */
  684.  
  685.     strcpy(SectionName, "File Names");
  686.     GetPrivateProfileString(SectionName, PROGNAME " Directory", "C:\\" PROGNAME, buffer, MAXLINELEN, OptionsFileName);
  687.     i = strlen(buffer);
  688.     if (i > 0 && buffer[i-1] != '\\') strcat(buffer, "\\");
  689.     global.jwppath = DupString(buffer);
  690.  
  691.     GetPrivateProfileString(SectionName, "Help File", PROGNAME ".HLP", buffer, MAXLINELEN, OptionsFileName);
  692.     global.help = DupString(buffer);
  693.     GetPrivateProfileString(SectionName, "Conversion Dictionary", "KANJIDCT.DCT", buffer, MAXLINELEN, OptionsFileName);
  694.     global.convdict = DupString(buffer);
  695.     GetPrivateProfileString(SectionName, "Conversion Dictionary Index", "KANJIDCT.IDX", buffer, MAXLINELEN, OptionsFileName);
  696.     global.convidx = DupString(buffer);
  697.     GetPrivateProfileString(SectionName, "User Conversion Dictionary", "USERDICT.DCT", buffer, MAXLINELEN, OptionsFileName);
  698.     global.userdict = DupString(buffer);
  699.     GetPrivateProfileString(SectionName, "Conversion Cache", "CNVCACHE.SAV", buffer, MAXLINELEN, OptionsFileName);
  700.     global.convcache = DupString(buffer);
  701.     GetPrivateProfileString(SectionName, "Japanese Dictionary", "EDICT", buffer, MAXLINELEN, OptionsFileName);
  702.     global.jdict = DupString(buffer);
  703.     GetPrivateProfileString(SectionName, "Japanese Dictionary Index", "EDICT.JDX", buffer, MAXLINELEN, OptionsFileName);
  704.     global.jdictidx = DupString(buffer);
  705.     GetPrivateProfileString(SectionName, "Kanji Info", "KINFO.DAT", buffer, MAXLINELEN, OptionsFileName);
  706.     global.kinfo = DupString(buffer);
  707.     GetPrivateProfileString(SectionName, "Kanji Info Index", "KINFO.IDX", buffer, MAXLINELEN, OptionsFileName);
  708.     global.kinfoidx = DupString(buffer);
  709.     GetPrivateProfileString(SectionName, "Global Glossary", "GLOSSARY.DAT", buffer, MAXLINELEN, OptionsFileName);
  710.     global.glossary = DupString(buffer);
  711.  
  712.     /* Page Setup */
  713.  
  714.     strcpy(SectionName, "Page Setup");
  715.     GetPrivateProfileString(SectionName, "Measurement Unit", "inches", buffer, MAXLINELEN, OptionsFileName);
  716.     global.measure = Measure = FindMeasurement(buffer, -1);
  717.     GetPrivateProfileString(SectionName, "Margins", "1.0  1.0  1.0  1.0", buffer, MAXLINELEN, OptionsFileName);
  718.     sscanf(buffer, "%lf %lf %lf %lf", &(global.pagesetup.margins[0]), &(global.pagesetup.margins[1]),
  719.                 &(global.pagesetup.margins[2]), &(global.pagesetup.margins[3]));
  720.     GetPrivateProfileString(SectionName, "Orientation", "Portrait", buffer, MAXLINELEN, OptionsFileName);
  721.  
  722.     if (!stricmp(buffer, "Portrait")) global.pagesetup.landscape = FALSE;
  723.     else if (!stricmp(buffer, "Landscape")) global.pagesetup.landscape = TRUE;
  724.     else global.pagesetup.landscape = FALSE;
  725.  
  726.     GetPrivateProfileString(SectionName, "Long Text Justification", "Justify", buffer, MAXLINELEN, OptionsFileName);
  727.     if (!stricmp(buffer, "Justify")) global.longjust = J_JUSTIFY;
  728.     else if (!strcmp(buffer, "Left")) global.longjust = J_LEFT;
  729.     else global.longjust = J_JUSTIFY;
  730.  
  731.     LongJust = global.longjust;
  732.  
  733.     GetPrivateProfileString(SectionName, "Short Text Justification", "Center", buffer, MAXLINELEN, OptionsFileName);
  734.     if (!stricmp(buffer, "Justify")) global.shortjust = J_JUSTIFY;
  735.     else if (!stricmp(buffer, "Left")) global.shortjust = J_LEFT;
  736.     else if (!stricmp(buffer, "Right")) global.shortjust = J_RIGHT;
  737.     else if (!stricmp(buffer, "Center")) global.shortjust = J_CENTER;
  738.     else global.shortjust = J_CENTER;
  739.  
  740.     ShortJust = global.shortjust;
  741.  
  742.     PageSetup = global.pagesetup;
  743.  
  744.  
  745.     /* ASCII Fonts */
  746.  
  747.     strcpy(SectionName, "Base ASCII Font");
  748.     GetPrivateProfileString(SectionName, "Face Name", "Times New Roman", buffer, MAXLINELEN, OptionsFileName);
  749.     DefAsciiFont.facename = DupString(buffer);
  750.     AsciiFontName = DupString(buffer);
  751.  
  752.     GetPrivateProfileString(SectionName, "Size", "12", buffer, MAXLINELEN, OptionsFileName);
  753.     AsciiFontSize = DefAsciiFont.size = atof(buffer);
  754.  
  755.     /* Installed Kanji Fonts */
  756.  
  757.     strcpy(SectionName, "Kanji Fonts");
  758.     global.nr_fonts = GetPrivateProfileInt(SectionName, "Number of Kanji Fonts", 0, OptionsFileName);
  759.  
  760.     SysFontNum = GetPrivateProfileInt(SectionName, "System Font", 1, OptionsFileName) - 1;
  761.     BaseFontNum = GetPrivateProfileInt(SectionName, "Default Base Font", 1, OptionsFileName) - 1;
  762.     PrintFontNum = GetPrivateProfileInt(SectionName, "Default Print Font", 1, OptionsFileName) - 1;
  763.  
  764.     GetPrivateProfileString(SectionName, "Default Print Scale", "1.0000", buffer, MAXLINELEN, OptionsFileName);
  765.     sscanf(buffer, "%lf", &(global.printscale));
  766.  
  767.     InstalledFonts = MemAlloc(global.nr_fonts * sizeof(KANJIFONT));
  768.  
  769.     PRINTFONT = SYSFONT = BASEFONT = NULL;
  770.  
  771.     for (i = j = 0; i < global.nr_fonts; i++) {
  772.         sprintf(keyname, "Font #%d", i+1);
  773.         GetPrivateProfileString(SectionName, keyname, "", buffer, MAXLINELEN, OptionsFileName);
  774.  
  775.         if (!buffer[0]) {
  776.             ErrorMessage(global.hwnd, "Cannot find entry for font #%d in JWP.INI!", i+1);
  777.         } else {
  778.             fd = OpenFont(buffer, &(InstalledFonts[j]));
  779.             if (fd < 0) {
  780.                 ErrorMessage(global.hwnd, "Cannot open kanji font %s!", buffer);
  781.                 exit(-1);
  782.             } else {
  783.                 close(fd);
  784.                 if (PrintFontNum == i) {
  785.                     PRINTFONT = &(InstalledFonts[j]);
  786.                     PrintFontNum = j;
  787.                 }
  788.                 if (SysFontNum == i) {
  789.                     SYSFONT = &(InstalledFonts[j]);
  790.                     SysFontNum = j;
  791.                 }
  792.                 if (BaseFontNum == i) {
  793.                     BASEFONT = &(InstalledFonts[j]);
  794.                     BaseFontNum = j;
  795.                 }
  796.                 j++;
  797.             }
  798.         }
  799.     }
  800.  
  801.     if (j <= 0) {
  802.         ErrorMessage(global.hwnd, "Cannot open any kanji font!");
  803.         exit(-1);
  804.     }
  805.  
  806.     if (PRINTFONT == NULL) {
  807.         PRINTFONT = &(InstalledFonts[0]);
  808.         PrintFontNum = 0;
  809.     }
  810.     if (SYSFONT == NULL) {
  811.         SYSFONT = &(InstalledFonts[0]);
  812.         SysFontNum = 0;
  813.     }
  814.     if (BASEFONT == NULL) {
  815.         BASEFONT = &(InstalledFonts[0]);
  816.         BaseFontNum = 0;
  817.     }
  818.  
  819.     global.nr_fonts = j;
  820.  
  821.     if (global.nr_fonts <= 0) {
  822.         ErrorMessage(global.hwnd, "No Installed fonts!\n\nProgram will die now.");
  823.         exit(-1);                               /* Cannot go on */
  824.     }
  825.  
  826.     /* Force even number spacing */
  827.  
  828.     if (SYSFONT->leading % 2 != 0) SYSFONT->leading++;
  829.     if (SYSFONT->spacing % 2 != 0) SYSFONT->spacing++;
  830.  
  831.     /* Glossary Options */
  832.  
  833.     strcpy(SectionName, "Glossary");
  834.     GetPrivateProfileString(SectionName, "Dynamic Glossary", "Yes", buffer, MAXLINELEN, OptionsFileName);
  835.     global.dynamicglossary = (buffer[0] == 'Y' || buffer[0] == 'y');
  836.     GetPrivateProfileString(SectionName, "Glossary List Disappears", "No", buffer, MAXLINELEN, OptionsFileName);
  837.     global.glistbehaviour = (buffer[0] == 'Y' || buffer[0] == 'y') ? 1 : 0;
  838.     GetPrivateProfileString(SectionName, "Glossary List Visible", "No", buffer, MAXLINELEN, OptionsFileName);
  839.     global.glistvisible = (buffer[0] == 'Y' || buffer[0] == 'y');
  840.     GetPrivateProfileString(SectionName, "Glossary List Position", "-1 -1", buffer, MAXLINELEN, OptionsFileName);
  841.     sscanf(buffer, "%d %d", &global.glistsize.left, &global.glistsize.top);
  842.     GetPrivateProfileString(SectionName, "Glossary List Size", "-1 -1", buffer, MAXLINELEN, OptionsFileName);
  843.     sscanf(buffer, "%d %d", &global.glistsize.right, &global.glistsize.bottom);
  844.  
  845.     glistsize = global.glistsize;
  846.  
  847.  
  848.     /* Undo Options */
  849.  
  850.     strcpy(SectionName, "Undo");
  851.     global.undolevels = GetPrivateProfileInt(SectionName, "Number of Undo Levels", DEFUNDOLEVELS, OptionsFileName);
  852.     UndoLevels = global.undolevels;
  853.     GetPrivateProfileString(SectionName, "Undo Levels Saved", "All", buffer, MAXLINELEN, OptionsFileName);
  854.     if (!stricmp(buffer, "All")) global.saveundolevels = -1;
  855.     else {
  856.         sscanf(buffer, "%d", &global.saveundolevels);
  857.     }
  858.     SaveUndoLevels = global.undolevels;
  859.  
  860.  
  861.     /* Other Options */
  862.  
  863.     strcpy(SectionName, "Others");
  864.     GetPrivateProfileString(SectionName, "Relax Margin for Punctuation", "Yes", buffer, MAXLINELEN, OptionsFileName);
  865.     global.relaxmargin = (buffer[0] == 'Y' || buffer[0] == 'y');
  866.     GetPrivateProfileString(SectionName, "Dynamic Conversion", "No", buffer, MAXLINELEN, OptionsFileName);
  867.     global.dynamicconvert = (buffer[0] == 'Y' || buffer[0] == 'y');
  868.     GetPrivateProfileString(SectionName, "Conversion Bar Position", "Bottom", buffer, MAXLINELEN, OptionsFileName);
  869.  
  870.     if (!stricmp(buffer, "Top")) global.listposition = 1;
  871.     else if (!stricmp(buffer, "Bottom")) global.listposition = 2;
  872.     else {
  873.         global.listposition = 0;
  874.         sscanf(buffer, "%d %d", &global.convbar.left, &global.convbar.top);
  875.     }
  876.  
  877.     GetPrivateProfileString(SectionName, "Conversion Bar Size", "-1 -1", buffer, MAXLINELEN, OptionsFileName);
  878.     sscanf(buffer, "%d %d", &global.convbar.right, &global.convbar.bottom);
  879.  
  880.     convbar = global.convbar;
  881.  
  882.     GetPrivateProfileString(SectionName, "Clipboard Format", "EUC", buffer, MAXLINELEN, OptionsFileName);
  883.     for (i = FF_EUC; FileFormatNames[i] != NULL; i++) {
  884.         if (!strcmp(FileFormatNames[i], buffer)) break;
  885.     }
  886.     if (FileFormatNames[i] != NULL) global.clipboard = i; else global.clipboard = FF_EUC;
  887.     clipboard = global.clipboard;
  888.  
  889.     GetPrivateProfileString(SectionName, "Draft View", "No", buffer, MAXLINELEN, OptionsFileName);
  890.     DraftView = global.draftview = (buffer[0] == 'Y' || buffer[0] == 'y');
  891.     GetPrivateProfileString(SectionName, "Show Special Symbols", "No", buffer, MAXLINELEN, OptionsFileName);
  892.     ShowSpecial = global.showspecial = (buffer[0] == 'Y' || buffer[0] == 'y');
  893.     GetPrivateProfileString(SectionName, "Show Iconbar", "Yes", buffer, MAXLINELEN, OptionsFileName);
  894.     global.showribbon = (buffer[0] == 'Y' || buffer[0] == 'y');
  895.     GetPrivateProfileString(SectionName, "Show Status Bar", "Yes", buffer, MAXLINELEN, OptionsFileName);
  896.     global.showstatus = (buffer[0] == 'Y' || buffer[0] == 'y');
  897.     GetPrivateProfileString(SectionName, "Show File Ruler", "Yes", buffer, MAXLINELEN, OptionsFileName);
  898.     ShowRuler = global.showruler = (buffer[0] == 'Y' || buffer[0] == 'y');
  899.     GetPrivateProfileString(SectionName, "3D Dialog Boxes", "Yes", buffer, MAXLINELEN, OptionsFileName);
  900.     Dialogs3D = global.ctl3d = (buffer[0] == 'Y' || buffer[0] == 'y');
  901.     GetPrivateProfileString(SectionName, "NN Conversion", "Yes", buffer, MAXLINELEN, OptionsFileName);
  902.     NNConvert = global.nnconvert = (buffer[0] == 'Y' || buffer[0] == 'y');
  903.  
  904.     /* Quick files */
  905.  
  906.     strcpy(SectionName, "Quick Files");
  907.  
  908.     j = GetPrivateProfileInt(SectionName, "Number of Quick Files", 0, OptionsFileName);
  909.     for (i = j; i > 0; i--) {
  910.         sprintf(keyname, "File%d", i);
  911.         GetPrivateProfileString(SectionName, keyname, "", buffer, MAXLINELEN, OptionsFileName);
  912.         if (buffer[0]) PutQuickFile(buffer);
  913.     }
  914.  
  915.     /* Hot keys */
  916.  
  917.     strcpy(SectionName, "Hot Keys");
  918.  
  919.     for (i = 0; i < NRJWPFUNC; i++) {
  920.         GetPrivateProfileString(SectionName, jwpfunc[i].desc, "None", buffer, MAXLINELEN, OptionsFileName);
  921.         if (!buffer[0] || !stricmp(buffer, "None")) continue;
  922.  
  923.         hotkey.ctrl = hotkey.shift = FALSE;
  924.         hotkey.alpha = hotkey.scancode = 0;
  925.  
  926.         for (j = 0; buffer[j]; j++) {
  927.             if (buffer[j] == SHIFTCHAR) {
  928.                 hotkey.shift = TRUE;
  929.             } else if (buffer[j] == CTRLCHAR) {
  930.                 ch = buffer[j+1];
  931.                 if ('a' <= ch && ch <= 'z') ch -= 32;
  932.                 if ('A' <= ch && ch <= 'Z' && (ch != 'F' || !buffer[j+2])) {
  933.                     hotkey.scancode = 0;
  934.                     hotkey.alpha = ch;
  935.                     hotkey.ctrl = TRUE;
  936.                     hotkey.shift = FALSE;
  937.                     break;
  938.                 }
  939.                 hotkey.ctrl = TRUE;
  940.             } else if (buffer[j] == 'F' || buffer[j] == 'f') {
  941.                 hotkey.alpha = 0;
  942.                 switch(atoi(buffer + j + 1)) {
  943.                     case 1: hotkey.scancode = VK_F1; break;
  944.                     case 2: hotkey.scancode = VK_F2; break;
  945.                     case 3: hotkey.scancode = VK_F3; break;
  946.                     case 4: hotkey.scancode = VK_F4; break;
  947.                     case 5: hotkey.scancode = VK_F5; break;
  948.                     case 6: hotkey.scancode = VK_F6; break;
  949.                     case 7: hotkey.scancode = VK_F7; break;
  950.                     case 8: hotkey.scancode = VK_F8; break;
  951.                     case 9: hotkey.scancode = VK_F9; break;
  952.                     case 10: hotkey.scancode = VK_F10; break;
  953.                     case 11: hotkey.scancode = VK_F11; break;
  954.                     case 12: hotkey.scancode = VK_F12; break;
  955.                 }
  956.                 break;
  957.             }
  958.         }
  959.  
  960.         if (hotkey.alpha != 0 || hotkey.scancode != 0) jwpfunc[i].hotkey = hotkey;
  961.     }
  962.  
  963.     ProcessMenuTexts();
  964.  
  965.     OptionsChanged = FALSE;
  966. }
  967.  
  968.  
  969.  
  970. void WriteOptionsFile (BOOL always)
  971. {
  972.     int i, fd;
  973.     FILE *fp;
  974.     OFSTRUCT of;
  975.     char buffer[MAXLINELEN];
  976.     BOOL DoIt = FALSE;
  977.     RECT progrect;
  978.     time_t t;
  979.  
  980.  
  981.     GetWindowRect(global.hwnd, &progrect);
  982.  
  983.     if (always || OptionsChanged) {
  984.         DoIt = TRUE;
  985.     } else {
  986.         /* Things that may change but do not affect OptionsChanged */
  987.  
  988.         if (global.glistvisible && global.glisthwnd == NULL) DoIt = TRUE;
  989.         if (!global.glistvisible && global.glisthwnd != NULL) DoIt = TRUE;
  990.  
  991.         if (global.statushwnd == NULL && global.showstatus) DoIt = TRUE;
  992.         if (global.statushwnd != NULL && !global.showstatus) DoIt = TRUE;
  993.  
  994.         if (global.tbhwnd == NULL && global.showribbon) DoIt = TRUE;
  995.         if (global.tbhwnd != NULL && !global.showribbon) DoIt = TRUE;
  996.  
  997.         if (fabs(AsciiFontSize - DefAsciiFont.size) > 0.01) DoIt = TRUE;
  998.         if (strcmp(AsciiFontName, DefAsciiFont.facename)) DoIt = TRUE;
  999.  
  1000.         if (memcmp(&glistsize, &global.glistsize, sizeof(RECT)) != 0) DoIt = TRUE;
  1001.         if (memcmp(&convbar, &global.convbar, sizeof(RECT)) != 0) DoIt = TRUE;
  1002.  
  1003.         if (clipboard != global.clipboard) DoIt = TRUE;
  1004.         if (global.draftview != DraftView) DoIt = TRUE;
  1005.         if (global.showspecial != ShowSpecial) DoIt = TRUE;
  1006.         if (global.showruler != ShowRuler) DoIt = TRUE;
  1007.         if (global.measure != Measure) DoIt = TRUE;
  1008.         if (global.longjust != LongJust) DoIt = TRUE;
  1009.         if (global.shortjust != ShortJust) DoIt = TRUE;
  1010.         if (global.ctl3d != Dialogs3D) DoIt = TRUE;
  1011.         if (global.nnconvert != NNConvert) DoIt = TRUE;
  1012.         if (global.undolevels != UndoLevels) DoIt = TRUE;
  1013.         if (global.saveundolevels != SaveUndoLevels) DoIt = TRUE;
  1014.  
  1015.         if (fabs(global.pagesetup.margins[0] - PageSetup.margins[0]) > 0.01) DoIt = TRUE;
  1016.         if (fabs(global.pagesetup.margins[1] - PageSetup.margins[1]) > 0.01) DoIt = TRUE;
  1017.         if (fabs(global.pagesetup.margins[2] - PageSetup.margins[2]) > 0.01) DoIt = TRUE;
  1018.         if (fabs(global.pagesetup.margins[3] - PageSetup.margins[3]) > 0.01) DoIt = TRUE;
  1019.         if (global.pagesetup.landscape != PageSetup.landscape) DoIt = TRUE;
  1020.  
  1021.         if (IsZoomed(global.hwnd)) {
  1022.             if (!ProgramMaximized) DoIt = TRUE;
  1023.         } else {
  1024.             if (ProgramMaximized) DoIt = TRUE;
  1025.             if (ProgramPosition.left != progrect.left) DoIt = TRUE;
  1026.             if (ProgramPosition.right != progrect.right) DoIt = TRUE;
  1027.             if (ProgramPosition.top != progrect.top) DoIt = TRUE;
  1028.             if (ProgramPosition.bottom != progrect.bottom) DoIt = TRUE;
  1029.         }
  1030.     }
  1031.  
  1032.     if (!DoIt) return;
  1033.  
  1034.  
  1035.     GetWindowsDirectory(buffer, MAXLINELEN);
  1036.     i = strlen(buffer);
  1037.     if (i > 0 && buffer[i-1] != '\\') {
  1038.         buffer[i] = '\\';
  1039.         buffer[i+1] = '\0';
  1040.     }
  1041.     strcat(buffer, PROGNAME ".INI");
  1042.  
  1043.     fd = OpenFile(buffer, &of, OF_WRITE | OF_CREATE);
  1044.     if (fd < 0) {
  1045.         ErrorMessage(global.hwnd, "Cannot write initialization file %s!", buffer);
  1046.         return;
  1047.     }
  1048.  
  1049.     fp = fdopen(fd, "wt");
  1050.     if (fp == NULL) {
  1051.         ErrorMessage(global.hwnd, "Cannot create " PROGNAME " initialization file!");
  1052.         close(fd);
  1053.         return;
  1054.     }
  1055.  
  1056.     /* Information */
  1057.  
  1058.     fprintf(fp, "; JWP.INI - Initialization file for JWP\n");
  1059.     fprintf(fp, "; Version 1.1\n");
  1060.     time(&t);
  1061.     fprintf(fp, "; Last Modified %s", ctime(&t));
  1062.  
  1063.     /* Path names */
  1064.  
  1065.     fprintf(fp, "\n[File Names]\n");
  1066.     fprintf(fp, "JWP Directory=%s\n", global.jwppath);
  1067.     fprintf(fp, "Help File=%s\n", global.help);
  1068.     fprintf(fp, "Conversion Dictionary=%s\n", global.convdict);
  1069.     fprintf(fp, "Conversion Dictionary Index=%s\n", global.convidx);
  1070.     fprintf(fp, "User Conversion Dictionary=%s\n", global.userdict);
  1071.     fprintf(fp, "Conversion Cache=%s\n", global.convcache);
  1072.     fprintf(fp, "Japanese Dictionary=%s\n", global.jdict);
  1073.     fprintf(fp, "Japanese Dictionary Index=%s\n", global.jdictidx);
  1074.     fprintf(fp, "Kanji Info=%s\n", global.kinfo);
  1075.     fprintf(fp, "Kanji Info Index=%s\n", global.kinfoidx);
  1076.     fprintf(fp, "Global Glossary=%s\n", global.glossary);
  1077.  
  1078.     /* Page Setup */
  1079.  
  1080.     fprintf(fp, "\n[Page Setup]\n");
  1081.     FindMeasurement(buffer, global.measure);
  1082.     fprintf(fp, "Measurement Unit=%s\n", buffer);
  1083.     fprintf(fp, "Margins=%4.2lf %4.2lf %4.2lf %4.2lf\n",
  1084.                 global.pagesetup.margins[0], global.pagesetup.margins[1],
  1085.                 global.pagesetup.margins[1], global.pagesetup.margins[3]);
  1086.     fprintf(fp, "Orientation=%s\n", global.pagesetup.landscape ? "Landscape" : "Portrait");
  1087.     fprintf(fp, "Long Text Justification=");
  1088.     switch (global.longjust) {
  1089.         case J_LEFT:    fprintf(fp, "Left\n"); break;
  1090.         default:
  1091.         case J_JUSTIFY: fprintf(fp, "Justify\n"); break;
  1092.     }
  1093.     fprintf(fp, "Short Text Justification=");
  1094.     switch (global.shortjust) {
  1095.         case J_LEFT:    fprintf(fp, "Left\n"); break;
  1096.         case J_RIGHT:   fprintf(fp, "Right\n"); break;
  1097.         default:
  1098.         case J_CENTER:  fprintf(fp, "Center\n"); break;
  1099.         case J_JUSTIFY: fprintf(fp, "Justify\n"); break;
  1100.     }
  1101.  
  1102.     /* ASCII Font */
  1103.  
  1104.     fprintf(fp, "\n[Base ASCII Font]\n");
  1105.     fprintf(fp, "Face Name=%s\n", DefAsciiFont.facename);
  1106.     fprintf(fp, "Size=%3.1lf\n", DefAsciiFont.size);
  1107.  
  1108.     /* Kanji Fonts */
  1109.  
  1110.     fprintf(fp, "\n[Kanji Fonts]\n");
  1111.     fprintf(fp, "Number of Kanji Fonts=%d\n", global.nr_fonts);
  1112.  
  1113.     fprintf(fp, "System Font=%d\n", SysFontNum + 1);
  1114.     fprintf(fp, "Default Base Font=%d\n", BaseFontNum + 1);
  1115.     fprintf(fp, "Default Print Font=%d\n", PrintFontNum + 1);
  1116.     fprintf(fp, "Default Print Scale=%6.4lf\n", global.printscale);
  1117.  
  1118.     for(i = 0; i < global.nr_fonts; i++) {
  1119.         fprintf(fp, "Font #%d=%s\n", i+1, InstalledFonts[i].filename);
  1120.     }
  1121.  
  1122.     /* Glossary Options */
  1123.  
  1124.     fprintf(fp, "\n[Glossary]\n");
  1125.     fprintf(fp, "Dynamic Glossary=%s\n", (global.dynamicglossary ? "Yes" : "No"));
  1126.     fprintf(fp, "Glossary List Disappears=%s\n", (global.glistbehaviour ? "Yes" : "No"));
  1127.     fprintf(fp, "Glossary List Visible=%s\n", (global.glisthwnd != NULL) ? "Yes" : "No");
  1128.     fprintf(fp, "Glossary List Position=%d %d\n", global.glistsize.left, global.glistsize.top);
  1129.     fprintf(fp, "Glossary List Size=%d %d\n", global.glistsize.right, global.glistsize.bottom);
  1130.  
  1131.     /* Undo Options */
  1132.  
  1133.     fprintf(fp, "\n[Undo]\n");
  1134.     if (global.undolevels < 0) {
  1135.         fprintf(fp, "Number of Undo Levels=0\n");
  1136.     } else {
  1137.         fprintf(fp, "Number of Undo Levels=%d\n", global.undolevels);
  1138.     }
  1139.     if (global.saveundolevels < 0) {
  1140.         fprintf(fp, "Undo Levels Saved=All\n");
  1141.     } else {
  1142.         fprintf(fp, "Undo Levels Saved=%d\n", global.saveundolevels);
  1143.     }
  1144.  
  1145.     /* Other Options */
  1146.  
  1147.     fprintf(fp, "\n[Others]\n");
  1148.  
  1149.     if (IsZoomed(global.hwnd)) {
  1150.         fprintf(fp, "Program Position=Maximized\n");
  1151.     } else {
  1152.         fprintf(fp, "Program Position=%d %d\n", progrect.left, progrect.top);
  1153.         fprintf(fp, "Program Size=%d %d\n", progrect.right - progrect.left,
  1154.                                             progrect.bottom - progrect.top);
  1155.     }
  1156.  
  1157.     fprintf(fp, "Relax Margin for Punctuation=%s\n", (global.relaxmargin ? "Yes" : "No"));
  1158.     fprintf(fp, "Dynamic Conversion=%s\n", (global.dynamicconvert ? "Yes" : "No"));
  1159.  
  1160.     switch (global.listposition) {
  1161.         case 0: fprintf(fp, "Conversion Bar Position=%d %d\n", global.convbar.left, global.convbar.top);
  1162.                 break;
  1163.         case 1: fprintf(fp, "Conversion Bar Position=Top\n");
  1164.                 break;
  1165.         default:
  1166.         case 2: fprintf(fp, "Conversion Bar Position=Bottom\n");
  1167.                 break;
  1168.     }
  1169.  
  1170.     fprintf(fp, "Conversion Bar Size=%d %d\n", global.convbar.right, global.convbar.bottom);
  1171.     fprintf(fp, "Clipboard Format=%s\n", FileFormatNames[global.clipboard]);
  1172.     fprintf(fp, "Draft View=%s\n", global.draftview ? "Yes" : "No");
  1173.     fprintf(fp, "Show Special Symbols=%s\n", global.showspecial ? "Yes" : "No");
  1174.     fprintf(fp, "Show Iconbar=%s\n", (global.tbhwnd != NULL) ? "Yes" : "No");
  1175.     fprintf(fp, "Show Status Bar=%s\n", (global.statushwnd != NULL) ? "Yes" : "No");
  1176.     fprintf(fp, "Show File Ruler=%s\n", global.showruler ? "Yes" : "No");
  1177.     fprintf(fp, "3D Dialog Boxes=%s\n", global.ctl3d ? "Yes" : "No");
  1178.     fprintf(fp, "NN Conversion=%s\n", global.nnconvert ? "Yes" : "No");
  1179.  
  1180.     /* Quick files */
  1181.  
  1182.     fprintf(fp, "\n[Quick Files]\n");
  1183.  
  1184.     for (i = 0; ; i++) {
  1185.         char *cp;
  1186.         extern char *GetQuickFile(int);
  1187.  
  1188.         cp = GetQuickFile(i);
  1189.         if (cp == NULL) break;
  1190.         fprintf(fp, "File%d=%s\n", i + 1, cp);
  1191.     }
  1192.  
  1193.     fprintf(fp, "Number of Quick Files=%d\n", i);
  1194.  
  1195.     /* Hot keys */
  1196.  
  1197.     fprintf(fp, "\n[Hot Keys]\n");
  1198.  
  1199.     for (i = 0; i < NRJWPFUNC; i++) {
  1200.         if (jwpfunc[i].hotkey.alpha == 0 && jwpfunc[i].hotkey.scancode == 0) {
  1201.             fprintf(fp, "%s=None\n", jwpfunc[i].desc);
  1202.             continue;
  1203.         }
  1204.  
  1205.         if (jwpfunc[i].hotkey.alpha != 0) {
  1206.             sprintf(buffer, "%c", CTRLCHAR);
  1207.             buffer[1] = jwpfunc[i].hotkey.alpha;
  1208.             buffer[2] = '\0';
  1209.         } else {
  1210.             if (jwpfunc[i].hotkey.ctrl) {
  1211.                 if (jwpfunc[i].hotkey.shift) sprintf(buffer, "%c%cF", SHIFTCHAR, CTRLCHAR);
  1212.                 else sprintf(buffer, "%cF", CTRLCHAR);
  1213.             } else {
  1214.                 if (jwpfunc[i].hotkey.shift) sprintf(buffer, "%cF", SHIFTCHAR);
  1215.                 else strcpy(buffer, "F");
  1216.             }
  1217.  
  1218.             switch (jwpfunc[i].hotkey.scancode) {
  1219.                 case VK_F1:  strcat(buffer, "1"); break;
  1220.                 case VK_F2:  strcat(buffer, "2"); break;
  1221.                 case VK_F3:  strcat(buffer, "3"); break;
  1222.                 case VK_F4:  strcat(buffer, "4"); break;
  1223.                 case VK_F5:  strcat(buffer, "5"); break;
  1224.                 case VK_F6:  strcat(buffer, "6"); break;
  1225.                 case VK_F7:  strcat(buffer, "7"); break;
  1226.                 case VK_F8:  strcat(buffer, "8"); break;
  1227.                 case VK_F9:  strcat(buffer, "9"); break;
  1228.                 case VK_F10: strcat(buffer, "10"); break;
  1229.                 case VK_F11: strcat(buffer, "11"); break;
  1230.                 case VK_F12: strcat(buffer, "12"); break;
  1231.                 default:     strcat(buffer, "0"); break;
  1232.             }
  1233.         }
  1234.  
  1235.         fprintf(fp, "%s=%s\n", jwpfunc[i].desc, buffer);
  1236.     }
  1237.  
  1238.     fclose(fp);
  1239. }
  1240.  
  1241.  
  1242.  
  1243. BOOL FAR PASCAL OptionsProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1244. {
  1245.     static FILEFORMAT OldCBFormat;
  1246.  
  1247.     switch (message) {
  1248.         case WM_INITDIALOG: {
  1249.             int i;
  1250.             char buffer[10];
  1251.  
  1252.             CheckDlgButton (hwnd, 4211, global.relaxmargin);
  1253.             CheckDlgButton (hwnd, 4212, global.dynamicconvert);
  1254.  
  1255. #ifdef CTL3D
  1256.             CheckDlgButton (hwnd, 4213, global.ctl3d);
  1257. #else CTL3D
  1258.             EnableWindow (GetDlgItem(hwnd, 4213), FALSE);
  1259. #endif CTL3D
  1260.             CheckDlgButton (hwnd, 4214, global.nnconvert);
  1261.             CheckDlgButton (hwnd, 4215, global.glistbehaviour);
  1262.  
  1263.             SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, FALSE, 0L);
  1264.             SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1265.             SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1266.  
  1267.             switch (global.listposition) {
  1268.                 case 0: SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, TRUE, 0L);
  1269.                         break;
  1270.                 case 1: SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, TRUE, 0L);
  1271.                         break;
  1272.                 case 2: SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, TRUE, 0L);
  1273.                         break;
  1274.             }
  1275.  
  1276.             SendDlgItemMessage(hwnd, 4231, BM_SETCHECK, FALSE, 0L);
  1277.             SendDlgItemMessage(hwnd, 4232, BM_SETCHECK, FALSE, 0L);
  1278.  
  1279.             switch (global.glistbehaviour) {
  1280.                 case 0: SendDlgItemMessage(hwnd, 4231, BM_SETCHECK, TRUE, 0L);
  1281.                         break;
  1282.                 case 1: SendDlgItemMessage(hwnd, 4232, BM_SETCHECK, TRUE, 0L);
  1283.                         break;
  1284.             }
  1285.  
  1286.             /* We start from EUC, skipping Unknown and Normal */
  1287.  
  1288.             for (i = FF_EUC; FileFormatNames[i] != NULL; i++)
  1289.                 SendDlgItemMessage(hwnd, 4241, CB_INSERTSTRING, -1, (LONG) ((LPSTR) FileFormatNames[i]));
  1290.             SendDlgItemMessage(hwnd, 4241, CB_SETCURSEL, global.clipboard - 2, 0L);
  1291.  
  1292.             OldCBFormat = global.clipboard;
  1293.  
  1294.             /* Levels of undo, several pre-set levels */
  1295.  
  1296.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "No Undo");
  1297.             SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 0, 0L);
  1298.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "1");
  1299.             if (global.undolevels >= 1) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 1, 0L);
  1300.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "5");
  1301.             if (global.undolevels >= 5) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 2, 0L);
  1302.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "10");
  1303.             if (global.undolevels >= 10) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 3, 0L);
  1304.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "50");
  1305.             if (global.undolevels >= 50) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 4, 0L);
  1306.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "100");
  1307.             if (global.undolevels >= 100) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 5, 0L);
  1308.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "500");
  1309.             if (global.undolevels >= 500) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 6, 0L);
  1310.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) "1000");
  1311.             if (global.undolevels >= 1000) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 7, 0L);
  1312.             sprintf(buffer, "%d", MAXUNDOLEVELS);
  1313.             SendDlgItemMessage(hwnd, 4242, CB_INSERTSTRING, -1, (LONG) buffer);
  1314.             if (global.undolevels >= MAXUNDOLEVELS) SendDlgItemMessage(hwnd, 4242, CB_SETCURSEL, 8, 0L);
  1315.  
  1316.             return (TRUE);
  1317.         }
  1318.  
  1319.         case WM_COMMAND:
  1320.             switch (wParam) {
  1321.                 case 4211:      /* Check boxes */
  1322.                 case 4212:
  1323.                 case 4213:
  1324.                 case 4214:
  1325.                     if (HIWORD(lParam) == BN_DOUBLECLICKED) SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1326.                     return (TRUE);
  1327.  
  1328.                 case 4221:      /* Top */
  1329.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, TRUE, 0L);
  1330.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1331.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1332.                     if (HIWORD(lParam) == BN_DOUBLECLICKED) SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1333.                     return (TRUE);
  1334.  
  1335.                 case 4222:      /* Bottom */
  1336.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, TRUE, 0L);
  1337.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, FALSE, 0L);
  1338.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, FALSE, 0L);
  1339.                     if (HIWORD(lParam) == BN_DOUBLECLICKED) SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1340.                     return (TRUE);
  1341.  
  1342.                 case 4223:      /* Floating */
  1343.                     SendDlgItemMessage(hwnd, 4223, BM_SETCHECK, TRUE, 0L);
  1344.                     SendDlgItemMessage(hwnd, 4221, BM_SETCHECK, FALSE, 0L);
  1345.                     SendDlgItemMessage(hwnd, 4222, BM_SETCHECK, FALSE, 0L);
  1346.                     if (HIWORD(lParam) == BN_DOUBLECLICKED) SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1347.                     return (TRUE);
  1348.  
  1349.                 case 4241: {        /* Clipboard format */
  1350.                     int i;
  1351.  
  1352.                     switch (HIWORD(lParam)) {
  1353.                         case LBN_SELCHANGE:
  1354.                         case LBN_DBLCLK:
  1355.                             i = (WORD) SendMessage(GetDlgItem(hwnd, 4241), CB_GETCURSEL, 0, 0L);
  1356.                             if (i == LB_ERR) {
  1357.                                 MessageBeep(0);
  1358.                                 return (TRUE);
  1359.                             }
  1360.                             global.clipboard = i + FF_EUC;   /* We start from EUC (2) */
  1361.  
  1362.                             if (HIWORD(lParam) == LBN_DBLCLK)
  1363.                                 SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1364.                             return (TRUE);
  1365.                     }
  1366.                     break;
  1367.                 }
  1368.  
  1369.                 case 4242:          /* Undo levels */
  1370.                     switch (HIWORD(lParam)) {
  1371.                         case LBN_DBLCLK:
  1372.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1373.                             return (TRUE);
  1374.                     }
  1375.                     break;
  1376.  
  1377.                 case IDOK: {
  1378.                     int i;
  1379.                     BOOL Redraw = FALSE;
  1380.                     RECT rect;
  1381.  
  1382.                     i = IsDlgButtonChecked(hwnd, 4211);
  1383.                     if (i != global.relaxmargin) OptionsChanged = TRUE;
  1384.                     global.relaxmargin = i;
  1385.  
  1386.                     i = IsDlgButtonChecked(hwnd, 4212);
  1387.                     if (i != global.dynamicconvert) OptionsChanged = TRUE;
  1388.                     global.dynamicconvert = i;
  1389.  
  1390. #ifdef CTL3D
  1391.                     i = IsDlgButtonChecked(hwnd, 4213);
  1392.                     if (i != global.ctl3d) OptionsChanged = TRUE;
  1393.                     global.ctl3d = i;
  1394.  
  1395.                     /*
  1396.                     if (global.ctl3d != Dialogs3D) {
  1397.                         char buffer[200];
  1398.  
  1399.                         sprintf(buffer, "You must exit " PROGNAME " and re-run "
  1400.                                         "it for 3D dialog boxes to %s.",
  1401.                                         Dialogs3D ? "disappear" : "appear");
  1402.                         MessageBeep(0);
  1403.                         MessageBox(hwnd, buffer, "A reminder...", MB_ICONASTERISK | MB_OK);
  1404.                     }
  1405.                     */
  1406. #endif CTL3D
  1407.  
  1408.                     i = IsDlgButtonChecked(hwnd, 4214);
  1409.                     if (i != global.nnconvert) OptionsChanged = TRUE;
  1410.                     global.nnconvert = i;
  1411.  
  1412.                     i = IsDlgButtonChecked(hwnd, 4215);
  1413.                     if (i != global.glistbehaviour) OptionsChanged = TRUE;
  1414.                     global.glistbehaviour = i;
  1415.  
  1416.                     if (IsDlgButtonChecked(hwnd, 4223)) {
  1417.                         if (global.listposition != 0) OptionsChanged = Redraw = TRUE;
  1418.                         global.listposition = 0;
  1419.                     } else if (IsDlgButtonChecked(hwnd, 4221)) {
  1420.                         if (global.listposition != 1) OptionsChanged = Redraw = TRUE;
  1421.                         global.listposition = 1;
  1422.                     } else {
  1423.                         if (global.listposition != 2) OptionsChanged = Redraw = TRUE;
  1424.                         global.listposition = 2;
  1425.                     }
  1426.  
  1427.                     i = (WORD) SendMessage(GetDlgItem(hwnd, 4242), CB_GETCURSEL, 0, 0L);
  1428.                     if (i != LB_ERR) {
  1429.                         switch (i) {
  1430.                             case 0: global.undolevels = 0; break;
  1431.                             case 1: global.undolevels = 1; break;
  1432.                             case 2: global.undolevels = 5; break;
  1433.                             case 3: global.undolevels = 10; break;
  1434.                             case 4: global.undolevels = 50; break;
  1435.                             case 5: global.undolevels = 100; break;
  1436.                             case 6: global.undolevels = 500; break;
  1437.                             case 7: global.undolevels = 1000; break;
  1438.                             case 8: global.undolevels = MAXUNDOLEVELS; break;
  1439.                         }
  1440.                     }
  1441.  
  1442.                     EndDialog(hwnd, FALSE);
  1443.  
  1444.                     if (Redraw) {
  1445.                         GetClientRect(global.hwnd, &rect);
  1446.                         i = rect.bottom - rect.top;
  1447.                         PostMessage(global.hwnd, WM_SIZE, 0, MAKELONG(rect.right - rect.left, i));
  1448.                     }
  1449.  
  1450.                     if (OldCBFormat != global.clipboard)
  1451.                         ResetClipboard();
  1452.  
  1453.                     return (TRUE);
  1454.                 }
  1455.  
  1456.                 case IDCANCEL:
  1457.                     EndDialog(hwnd, FALSE);
  1458.                     return (TRUE);
  1459.             }
  1460.     }
  1461.  
  1462.     return (FALSE);
  1463. }
  1464.  
  1465.  
  1466.  
  1467. static KANJI far *ConvertFontName (int id, LONG lParam, KANJI *buf)
  1468. {
  1469.     int i, j;
  1470.     KANJI *kp;
  1471.     char tempbuf[50];
  1472.  
  1473.     kp = InstalledFonts[lParam].facename;
  1474.  
  1475.     for (i = 0; kp[i]; i++) buf[i] = kp[i];
  1476.  
  1477.     sprintf(tempbuf, " (%d x %d)", InstalledFonts[lParam].width, InstalledFonts[lParam].height);
  1478.  
  1479.     for (j = 0; tempbuf[j]; j++) buf[i++] = tempbuf[j];
  1480.     buf[i] = 0;
  1481.  
  1482.     return (buf);
  1483. }
  1484.  
  1485.  
  1486.  
  1487. short FAR PASCAL AsciiFontEnumProc (LOGFONT far *lf, TEXTMETRIC far *tm, short ftype, LPSTR data)
  1488. {
  1489.     int i, len;
  1490.     HWND hwnd;
  1491.     char buffer[MAXLINELEN];
  1492.     char temp[MAXLINELEN];
  1493.  
  1494.     hwnd = (HWND) data;
  1495.  
  1496.     if (ftype & DEVICE_FONTTYPE) {
  1497.         buffer[0] = '*';
  1498.         _fstrcpy(buffer + 1, lf->lfFaceName);
  1499.     } else {
  1500.         _fstrcpy(buffer, lf->lfFaceName);
  1501.     }
  1502.  
  1503.     len = SendMessage(hwnd, CB_GETCOUNT, 0, 0L);
  1504.  
  1505.     for (i = 0; i < len; i++) {
  1506.         SendMessage(hwnd, CB_GETLBTEXT, i, (LONG) ((char far *) temp));
  1507.         if (!stricmp(buffer, temp)) return (1);
  1508.     }
  1509.  
  1510.     SendMessage(hwnd, CB_ADDSTRING, 0, (LONG) buffer);
  1511.  
  1512.     return (1);
  1513. }
  1514.  
  1515.  
  1516.  
  1517. short FAR PASCAL AsciiFontSizeEnumProc (LOGFONT far *lf, TEXTMETRIC far *tm, short ftype, LPSTR data)
  1518. {
  1519.     int i, j, len, dpi;
  1520.     double ps;
  1521.     HDC hdc;
  1522.  
  1523.     if (!(ftype & RASTER_FONTTYPE) || (ftype & TTYPE_FONTTYPE)) {
  1524.         for (i = 8, j = 0; i <= 24; i++) PointSizes[j++] = i;
  1525.         PointSizes[j++] = 36.0;
  1526.         PointSizes[j++] = 48.0;
  1527.         PointSizes[j] = 0.0;
  1528.  
  1529.         return (1);
  1530.     }
  1531.  
  1532.     len = SegHeapGetSize(PointSizes) / sizeof(double);
  1533.  
  1534.     hdc = (HDC) data;
  1535.  
  1536.     dpi = GetDeviceCaps(hdc, LOGPIXELSY);
  1537.     ps = ((double) tm->tmHeight - (double) tm->tmInternalLeading) * 72.0 / (double) dpi;
  1538.  
  1539.     for (i = 0; i < len; i++) {
  1540.         if (PointSizes[i] == 0.0) break;
  1541.         if (fabs(ps - PointSizes[i]) < 0.01) return (0);
  1542.     }
  1543.  
  1544.     if (i >= len) PointSizes = (double far *) BlockRealloc(PointSizes, (len + PSBLOCKSIZE) * sizeof(double));
  1545.  
  1546.     PointSizes[i++] = ps;
  1547.     PointSizes[i] = 0.0;
  1548.  
  1549.     return (0);
  1550. }
  1551.  
  1552.  
  1553.  
  1554. static void FillAuxStuff (HWND hwnd, int group, int window, int font, double scale)
  1555. {
  1556.     int len;
  1557.     double dpp, ps;
  1558.     char buffer[MAXLINELEN];
  1559.  
  1560.     /* Fill in some aux stuff */
  1561.  
  1562.     dpp = (double) global.resolution.y / 72.0;
  1563.     ps = ((double) InstalledFonts[font].height * scale) / dpp;
  1564.     sprintf(buffer, "Kanji Printing Size = %3.1lf point%s",
  1565.             ps, (ps > 1.10) ? "s" : "");
  1566.     SetDlgItemText(hwnd, group, buffer);
  1567.     sprintf(buffer, "%3.1lf", ps);
  1568.     len = strlen(buffer);
  1569.     if (len > 2 && buffer[len-1] == '0') buffer[len-2] = '\0';
  1570.     SetDlgItemText(hwnd, window, buffer);
  1571. }
  1572.  
  1573.  
  1574.  
  1575. static void FillPointSizes (HWND hwnd, int window, char *facename, double ps)
  1576. {
  1577.     int i, len;
  1578.     double itemps;
  1579.     char buffer[20];
  1580.     HDC hdc;
  1581.     FARPROC enumproc;
  1582.  
  1583.     SendDlgItemMessage(hwnd, window, WM_SETREDRAW, FALSE, 0L);
  1584.     SendDlgItemMessage(hwnd, window, CB_RESETCONTENT, 0, 0L);
  1585.  
  1586.     hdc = GetPrinterDC(TRUE, NULL);
  1587.     if (hdc == NULL) hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  1588.  
  1589.     if (*facename == '*') facename++;
  1590.  
  1591.     PointSizes = (double far *) BlockAlloc(sizeof(double) * PSBLOCKSIZE);
  1592.     PointSizes[0] = 0.0;
  1593.  
  1594.     enumproc = MakeProcInstance((FARPROC) AsciiFontSizeEnumProc, hInstance);
  1595.     EnumFonts (hdc, facename, enumproc, (LONG) hdc);
  1596.     FreeProcInstance(enumproc);
  1597.  
  1598.     for (i = 0; PointSizes[i] != 0.0; i++) {
  1599.         sprintf(buffer, "%3.1lf", PointSizes[i]);
  1600.  
  1601.         len = strlen(buffer);
  1602.         if (buffer[len - 1] == '0') buffer[len - 2] = '\0';
  1603.  
  1604.         SendDlgItemMessage(hwnd, window, CB_ADDSTRING, 0, (LONG) ((char far *) buffer));
  1605.     }
  1606.     FreeBlock(PointSizes);
  1607.  
  1608.     len = SendDlgItemMessage(hwnd, window, CB_GETCOUNT, 0, 0L);
  1609.     for (i = 0; i < len; i++) {
  1610.         SendDlgItemMessage(hwnd, window, CB_GETLBTEXT, i, (LONG) ((char far *) buffer));
  1611.         itemps = atof(buffer);
  1612.         if (fabs(itemps - ps) < 0.01) break;
  1613.     }
  1614.  
  1615.     if (i < len) SendDlgItemMessage(hwnd, window, CB_SETCURSEL, i, 0L);
  1616.     DeleteDC(hdc);
  1617.  
  1618.     SendDlgItemMessage(hwnd, window, WM_SETREDRAW, TRUE, 0L);
  1619.     InvalidateRect(GetDlgItem(hwnd, window), NULL, TRUE);
  1620. }
  1621.  
  1622.  
  1623.  
  1624. BOOL FAR PASCAL InstalledFontsProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
  1625. {
  1626.     switch (message) {
  1627.         case WM_INITDIALOG: {
  1628.             int i, len;
  1629.             HDC hdc;
  1630.             FARPROC enumproc;
  1631.             char buffer[MAXLINELEN];
  1632.  
  1633.             SendDlgItemMessage(hwnd, 4231, EM_LIMITTEXT, 4, 0L);
  1634.             SendDlgItemMessage(hwnd, 4202, CB_LIMITTEXT, 4, 0L);
  1635.  
  1636.             /* Fill in the ASCII font box */
  1637.  
  1638.             hdc = GetPrinterDC(TRUE, NULL);
  1639.             if (hdc == NULL) hdc = CreateIC("DISPLAY", NULL, NULL, NULL);
  1640.  
  1641.             enumproc = MakeProcInstance((FARPROC) AsciiFontEnumProc, hInstance);
  1642.             EnumFonts (hdc, NULL, enumproc, (LONG) GetDlgItem(hwnd, 4201));
  1643.             FreeProcInstance(enumproc);
  1644.  
  1645.             len = SendDlgItemMessage(hwnd, 4201, CB_GETCOUNT, 0, 0L);
  1646.             for (i = 0; i < len; i++) {
  1647.                 SendDlgItemMessage(hwnd, 4201, CB_GETLBTEXT, i, (LONG) ((char far *) buffer));
  1648.                 if (buffer[0] == '*') {
  1649.                     if (!strcmp(buffer + 1, DefAsciiFont.facename)) break;
  1650.                 } else {
  1651.                     if (!strcmp(buffer, DefAsciiFont.facename)) break;
  1652.                 }
  1653.             }
  1654.  
  1655.             if (i < len) {
  1656.                 SendDlgItemMessage(hwnd, 4201, CB_SETCURSEL, i, 0L);
  1657.                 FillPointSizes(hwnd, 4202, buffer, DefAsciiFont.size);
  1658.             }
  1659.             DeleteDC(hdc);
  1660.  
  1661.  
  1662.             /* Fill in all the kanji font boxes */
  1663.  
  1664.             for (i = 0; i < global.nr_fonts; i++) {
  1665.                 SendDlgItemMessage(hwnd, 4211, CB_ADDSTRING, 0, (LONG) i);
  1666.                 SendDlgItemMessage(hwnd, 4221, CB_ADDSTRING, 0, (LONG) i);
  1667.             }
  1668.  
  1669.             /* Select the right items */
  1670.  
  1671.             for (i = 0; i < global.nr_fonts; i++) {
  1672.                 if (SendDlgItemMessage(hwnd, 4211, CB_GETITEMDATA, i, 0L) == BaseFontNum) {
  1673.                     SendDlgItemMessage(hwnd, 4211, CB_SETCURSEL, i, 0L);
  1674.                 }
  1675.                 if (SendDlgItemMessage(hwnd, 4221, CB_GETITEMDATA, i, 0L) == PrintFontNum) {
  1676.                     SendDlgItemMessage(hwnd, 4221, CB_SETCURSEL, i, 0L);
  1677.                     FillAuxStuff(hwnd, 4232, 4231, PrintFontNum, global.printscale);
  1678.                 }
  1679.             }
  1680.  
  1681.             SetFocus(GetDlgItem(hwnd, 4201));
  1682.             CenterDialogBox(hwnd);
  1683.             return (TRUE);
  1684.         }
  1685.  
  1686.         case WM_COMMAND: {
  1687.             int i, j;
  1688.             BOOL NeedReformat;
  1689.             double ratio, ps;
  1690.             char buffer[MAXLINELEN];
  1691.  
  1692.             switch (wParam) {
  1693.                 case 4211:      /* Base font */
  1694.                     switch (HIWORD(lParam)) {
  1695.                         case CBN_DBLCLK:
  1696.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1697.                             return (TRUE);
  1698.                     }
  1699.                     return (TRUE);
  1700.  
  1701.                 case 4201:      /* ASCII font */
  1702.                     switch (HIWORD(lParam)) {
  1703.                         case CBN_SELCHANGE:
  1704.                             i = SendDlgItemMessage(hwnd, 4201, CB_GETCURSEL, 0, 0L);
  1705.  
  1706.                             if (i != CB_ERR) {  /* Update the point size */
  1707.                                 SendDlgItemMessage(hwnd, 4201, CB_GETLBTEXT, i, (LONG) ((char far *) buffer));
  1708.                                 FillPointSizes(hwnd, 4202, buffer, DefAsciiFont.size);
  1709.                             }
  1710.                             return (TRUE);
  1711.  
  1712.                         case CBN_DBLCLK:
  1713.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1714.                             return (TRUE);
  1715.                     }
  1716.                     return (TRUE);
  1717.  
  1718.                 case 4221:      /* Print font */
  1719.                     switch (HIWORD(lParam)) {
  1720.                         case CBN_SELCHANGE:
  1721.                             i = SendDlgItemMessage(hwnd, 4221, CB_GETCURSEL, 0, 0L);
  1722.                             if (i != CB_ERR) {  /* Update the point size */
  1723.                                 j = SendDlgItemMessage(hwnd, 4221, CB_GETITEMDATA, i, 0L);
  1724.                                 FillAuxStuff(hwnd, 4232, 4231, j, 1.0);
  1725.                             }
  1726.                             return (TRUE);
  1727.  
  1728.                         case CBN_DBLCLK:
  1729.                             SendMessage(hwnd, WM_COMMAND, IDOK, 0L);
  1730.                             return (TRUE);
  1731.                     }
  1732.                     return (TRUE);
  1733.  
  1734.                 case IDOK:
  1735.                     NeedReformat = FALSE;
  1736.  
  1737.                     /* Check the base font */
  1738.  
  1739.                     i = SendDlgItemMessage(hwnd, 4211, CB_GETCURSEL, 0, 0L);
  1740.                     if (i != CB_ERR) {
  1741.                         j = SendDlgItemMessage(hwnd, 4211, CB_GETITEMDATA, i, 0L);
  1742.                         if (j != BaseFontNum) {
  1743.                             BaseFontNum = j;
  1744.                             BASEFONT = &(InstalledFonts[j]);
  1745.                             NeedReformat = OptionsChanged = TRUE;
  1746.                         }
  1747.                     }
  1748.  
  1749.                     /* Check the printing font */
  1750.  
  1751.                     i = SendDlgItemMessage(hwnd, 4221, CB_GETCURSEL, 0, 0L);
  1752.                     if (i != CB_ERR) {
  1753.                         j = SendDlgItemMessage(hwnd, 4221, CB_GETITEMDATA, i, 0L);
  1754.                         if (j != PrintFontNum) {
  1755.                             PrintFontNum = j;
  1756.                             PRINTFONT = &(InstalledFonts[j]);
  1757.                             NeedReformat = OptionsChanged = TRUE;
  1758.                         }
  1759.                     }
  1760.  
  1761.                     /* Is the aspect ratio OK? */
  1762.  
  1763.                     ratio = (double) InstalledFonts[BaseFontNum].width /
  1764.                                 (double) InstalledFonts[BaseFontNum].height;
  1765.                     ratio /= ((double) InstalledFonts[PrintFontNum].width /
  1766.                                  (double) InstalledFonts[PrintFontNum].height);
  1767.  
  1768.                     if (fabs(ratio - 1.0) > 0.01) {
  1769.                         ErrorMessage(hwnd, "The kanji font for display and printing must "
  1770.                                               "have the same aspect ratio!");
  1771.                         return (TRUE);
  1772.                     }
  1773.  
  1774.                     /* Check the printing scale */
  1775.  
  1776.                     GetDlgItemText(hwnd, 4231, buffer, 5);
  1777.                     ps = atof(buffer);       /* Printing point size */
  1778.  
  1779.                     GetDlgItemText(hwnd, 4202, buffer, 5);
  1780.  
  1781.                     if (atof(buffer) - ps > 0.01) {
  1782.                         ErrorMessage(hwnd, "WARNING!  You have chosen a text font that is larger "
  1783.                                               "than the kanji print font!");
  1784.                     }
  1785.  
  1786.                     j = (int) floor(ps * (double) global.resolution.y / 72.0 + 0.5);      /* dots */
  1787.  
  1788.                     ratio = (double) j / (double) InstalledFonts[PrintFontNum].height;
  1789.  
  1790.                     if (fabs(global.printscale - ratio) > 0.01) {
  1791.                         global.printscale = ratio;
  1792.                         NeedReformat = OptionsChanged = TRUE;
  1793.                     }
  1794.  
  1795.                     /* ASCII font */
  1796.  
  1797.                     GetDlgItemText(hwnd, 4201, buffer, MAXLINELEN);
  1798.                     if (strcmp(DefAsciiFont.facename, buffer)) {
  1799.                         FreeMem(DefAsciiFont.facename);
  1800.                         if (buffer[0] == '*') {
  1801.                             DefAsciiFont.facename = DupString(buffer + 1);
  1802.                         } else {
  1803.                             DefAsciiFont.facename = DupString(buffer);
  1804.                         }
  1805.                         NeedReformat = OptionsChanged = TRUE;
  1806.                     }
  1807.                     GetDlgItemText(hwnd, 4202, buffer, 5);
  1808.                     ps = atof(buffer);
  1809.                     if (ps >= 0.01 && fabs(ps - DefAsciiFont.size) > 0.01) {
  1810.                         DefAsciiFont.size = ps;
  1811.                         NeedReformat = OptionsChanged = TRUE;
  1812.                     }
  1813.  
  1814.                     EndDialog(hwnd, NeedReformat);
  1815.                     return (TRUE);
  1816.  
  1817.                 case IDCANCEL:
  1818.                     EndDialog(hwnd, FALSE);
  1819.                     return (TRUE);
  1820.             }
  1821.             return (FALSE);
  1822.         }
  1823.  
  1824.         case WM_COMPAREITEM:
  1825.         case WM_DELETEITEM:
  1826.         case WM_DRAWITEM:
  1827.         case WM_MEASUREITEM:
  1828.             return (JlistProc(hwnd, message, wParam, lParam, TRUE, ConvertFontName));
  1829.     }
  1830.  
  1831.     return (FALSE);
  1832. }
  1833.